package com.sand.service.Impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.injector.methods.SelectCount;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sand.AppJwtUtil;
import com.sand.Exception.SandException;

import com.sand.VerificationCode;
import com.sand.Worker.WorkertType;
import com.sand.dto.Owner.AddOwner;
import com.sand.dto.Select.UserSelect;
import com.sand.dto.merchant.AddMerchant;
import com.sand.dto.supplier.AddSupplier;
import com.sand.dto.user.*;

import com.sand.dto.worker.AddWorker;
import com.sand.entity.user.User;

import com.sand.feign.merchantFeign;
import com.sand.feign.ownerFeign;
import com.sand.feign.workerFeign;
import com.sand.mapper.UserMapper;
import com.sand.feign.supplierFeign;
import com.sand.merchant.Permission;
import com.sand.owner.Intentionality;
import com.sand.result.AppHttpCodeEnum;

import com.sand.service.UserService;
import com.sand.user.UserGneder;
import com.sand.user.UserStatus;
import com.sand.user.UserType;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;


import java.util.*;

@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {


    public final merchantFeign merchantFeign;

    public final ownerFeign ownerFeign;

    public final supplierFeign supplierFeign;

    public final workerFeign workerFeign;

    public final UserMapper userMapper;


    /**
     * 默认商家没有权限
     */
    public final Integer permission = Permission.NO;

    /**
     * 默认客户意向度一般
     */
    public final Integer intentionality = Intentionality.BAN;

    /**
     * 默认工人类型为全能
     */
    public final Integer workertype = WorkertType.QUAN;

    public UserServiceImpl(merchantFeign merchantFeign, ownerFeign ownerFeign, supplierFeign supplierFeign, workerFeign workerFeign, UserMapper userMapper) {
        this.merchantFeign = merchantFeign;
        this.ownerFeign = ownerFeign;
        this.supplierFeign = supplierFeign;
        this.workerFeign = workerFeign;
        this.userMapper = userMapper;
    }


    /**
     * 用户登录
     *
     */
    @Override
    public Map<String, Object> login(UserLogin login) {

        //获取手机号
        String phone = login.getPhone();

        //获取密码
        String password = login.getPassword();

        //参数校验
        if (StringUtils.isNotBlank(phone) && !(StringUtils.isNotBlank(password))) {
            throw new SandException(AppHttpCodeEnum.PARAM_INVALID, "未输入密码");
        }

        if (!StringUtils.isNotBlank(phone) && (StringUtils.isNotBlank(password))) {
            throw new SandException(AppHttpCodeEnum.PARAM_INVALID, "未输入手机号");
        }

        //1正常登录
        if (StringUtils.isNotBlank(phone) && StringUtils.isNotBlank(password)) {


            //1.2根据手机号查询用户
            User apUser = getOne(Wrappers.<User>lambdaQuery().eq(User::getPhone, phone));

            if (apUser == null) {
                throw new SandException(AppHttpCodeEnum.DATA_NOT_EXIST, "该用户不存在");
            }

            //1.5判断跟获取的该用户的密码是否相等
            if (!apUser.getPassword().equals(password)) {
                throw new SandException(AppHttpCodeEnum.LOGIN_PASSWORD_ERROR);
            }

            //对于状态停止的用户不进行登录
            if (apUser.getStatus() == UserStatus.NO_EXIST) {
                throw new SandException(AppHttpCodeEnum.LOGIN_PASSWORD_ERROR, "该用户已被停止,无法登录请联系管理员");
            }

            //1.6登录成功返回jwt令牌(用户id生成)
            Map<String, Object> map = new HashMap<>();

            //利用工具生成
            String token = AppJwtUtil.getToken(apUser.getId());

            //添加到集合返回
            map.put("token", token);
            map.put("user", apUser);

            return map;
        } else {
            //游客登录
            HashMap<String, Object> map = new HashMap<>();
            //返回jwt立牌就行,设置id为0
            String token = AppJwtUtil.getToken(0);
            //设置token
            map.put("token", token);
            map.put("user", "");
            return map;
        }
    }

    /**
     * 添加用户
     *
     */
    @Override
    public String add(AddUserDto userAddDto) {

        //拼接一个user
        User user = new User();

        BeanUtils.copyProperties(userAddDto, user);

        //用户字段校验
        pan(user , 1);

        //新增用户
        save(user);

        //添加到对应的人员表
        addUser(user);

        return "添加用户成功";

    }


    /**
     * 查询用户
     *
     */
    @Override
    public User inquire(UserSelect userSelect) {

        String phone = userSelect.getPhone();

        Integer id = userSelect.getId();

        //如果2个都没有传入
        if (id == null && phone.isEmpty()) {
            throw new SandException(AppHttpCodeEnum.PARAM_INVALID, "未传入要查到的人员的id或手机号");
        }

        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();

        if (id != null) {
            wrapper.eq(User::getId, id);
        }

        if (phone != null && !phone.isEmpty()) {
            wrapper.eq(User::getPhone, phone);
        }

        User user = getOne(wrapper);

        if (user == null) {
            throw new SandException(AppHttpCodeEnum.PARAM_INVALID, "传入的用户id有误");
        }

        user.setPassword("");

        return user;

    }

    /**
     * 根据条件查询用户
     */
    @Override
    public List<User> getList(UserSelectList list) {

        //参数完整确认
        if (list.getPage() == null || list.getPageSize() == null) {
            throw new SandException(AppHttpCodeEnum.PARAM_INVALID, "未传入要查询的页数和码数");
        }

        //查询参数初始话
        ininter(list);

        //判断式
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();

        //分页
        Page<User> userPage = new Page<>(list.getPage(), list.getPageSize());

        //过滤
        warpp(list, wrapper);

        Page<User> page = page(userPage, wrapper);

        //获取查询到的数据
        List<User> userList = page.getRecords();

        //设置隐私
        return userList.stream().peek(user -> user.setPassword("")).toList();
    }

    /**
     * 根据多个id返回多个用户基本数据
     *
     */
    @Override
    public List<User> ids(Integer[] ids) {
        if (ids == null) {
            throw new SandException(AppHttpCodeEnum.PARAM_INVALID, "为传入id");
        }

        List<Integer> list = Arrays.asList(ids);

        return userMapper.selectBatchIds(list);
    }

    /**
     * 修改用户
     */
    @Override
    public String UserUpate(UserUpdate userUpdate) {

        if (userUpdate.getId() == null) {
            throw new SandException(AppHttpCodeEnum.PARAM_INVALID, "没有传入要修改的id");
        }

        User user = new User();

        BeanUtils.copyProperties(userUpdate,user);

        //参数判断
        pan(user , 0);

        updateById(user);

        return "修改成功";
    }

    /**
     * 修改用户状态
     */
    @Override
    public String status(Integer id) {

        if (id == null){
            throw new SandException(AppHttpCodeEnum.PARAM_INVALID,"没有传入id");
        }

        User user = getById(id);

        Integer i = user.getStatus();

        if (i == 0){
            user.setStatus(1);
        }else{
            user.setStatus(0);
        }

        updateById(user);

        return "修改状态成功";
    }

    /**
     * 修改密码
     */
    @Override
    public String UpdatePassword(UserUpdatePassword updatePassword) {

        Integer id = updatePassword.getId();

        String password = updatePassword.getPassword();

        if (id == null){
            throw new SandException(AppHttpCodeEnum.PARAM_INVALID,"没有传入要修改的用户");
        }

        if (password == null){
            throw new SandException(AppHttpCodeEnum.PARAM_INVALID,"没有传入要修改的密码");
        }

        LambdaUpdateWrapper<User> wrapper = new UpdateWrapper<User>().lambda().eq(User::getId, id).set(User::getPassword, password);

        try {
            update(wrapper);
        } catch (Exception e) {
            throw new SandException(AppHttpCodeEnum.PARAM_INVALID,"修改密码失败");
        }

        return "修改密码成功";
    }

    //获取所有用户数量
    @Override
    public UserAmount amount() {

        //根据数据库表名称获取总条数
        String[] strings = {"user","merchant","owner","worker","supplier"};

        Long[] integers = new Long[5];

        UserAmount amount = new UserAmount();

        int i = 0;

        for (int k = 0; k < strings.length; k++) {
            String name = strings[k];
            long l = userMapper.countTable(name);
            integers[k] = l;
        }

        amount.setCount(integers[i]);
        amount.setMerchant(integers[i+1]);
        amount.setOwner(integers[i+2]);
        amount.setWorker(integers[i+3]);
        amount.setSupplier(integers[i+4]);

        return amount;
    }

    /**
     * 修改电话号码(后期可以采用验证码校验)
     */
    @Override
    public String updatePhone(UserUpdatePhone updatePhone) {

        Integer id = updatePhone.getId();

        String phone = updatePhone.getPhone();

        if (id == null || phone.isEmpty()){
            throw new SandException(AppHttpCodeEnum.PARAM_INVALID,"没有传入id或电话号码");
        }

        //根据id查询用户
        User user = getById(id);

        if (user == null){
            throw new SandException(AppHttpCodeEnum.PARAM_INVALID,"当前用户不存在");
        }

        //电话号码校验
        if (phone.length() != 11){
            throw new SandException(AppHttpCodeEnum.PARAM_INVALID,"电话格式不对");
        }

        //根据电话查询用户
        User one = getOne(new LambdaQueryWrapper<User>().eq(User::getPhone, phone));

        if (one != null){
            throw new SandException(AppHttpCodeEnum.PARAM_INVALID,"改电话号码已被注册");
        }

        //修改电话号码
        user.setPhone(phone);

        try {
            updateById(user);
        } catch (Exception e) {
            throw new SandException(AppHttpCodeEnum.PARAM_INVALID,"修改电话号码失败");
        }

        return "修改电话号码成功";
    }

    //获取验证码
    @Override
    public String YanZengMa(String yzm) {

        //随机生成6未验证码
        String str = VerificationCode.generateVerificationCode();

        log.info("生成验证码为: {}",str);

        //保存到redis中

        return str;
    }


    //查询参数默认话
    private static void ininter(UserSelectList list) {
        if (list.getMinAge() == null) {
            list.setMinAge(18);
        }

        if (list.getMaxAge() == null) {
            list.setMaxAge(100);
        }

        if (list.getStatus() == null) {
            list.setStatus(1);
        }
    }

    //查询所有用户过滤
    private static void warpp(UserSelectList list, LambdaQueryWrapper<User> wrapper) {
        // 类型不传默认查询所有
        if (list.getType() != null) {
            wrapper.eq(User::getType, list.getType());
        }

        // 姓名采用模糊匹配默认查询所有
        if (!list.getName().isEmpty()) {
            wrapper.like(User::getName, list.getName());
        }

        // 年龄使用范围查询
        wrapper.between(User::getAge, list.getMinAge(), list.getMaxAge());

        // 状态不传默认查询建康的用户
        wrapper.eq(User::getStatus, list.getStatus());

        // 地址模糊匹配查询
        if (list.getAddr() != null && list.getAddr().toString().isEmpty()) {
            Addr addr = list.getAddr();

            String string = addr.getProvince() + addr.getCity() + addr.getDistrict() + addr.getSpecific();

            wrapper.like(User::getAddr, string);

        }

    }


    /**
     * 用户字段判断
     */
    private void pan(User user , Integer i) {

        //传入的数据
        String name = user.getName();
        Integer age = user.getAge();
        Integer gender = user.getGender();
        Integer type = user.getType();
        String phone = user.getPhone();
        String password = user.getPassword();
        String addr = user.getAddr();
        String text = user.getText();

        //非空判断
        panNull(user , i);

        //姓名校验
        if (name.length() > 6) {
            throw new SandException(AppHttpCodeEnum.PARAM_INVALID, "长度不能超过6位");
        }

        //年龄校验
        if (age >= 100 || age < 18) {
            throw new SandException(AppHttpCodeEnum.PARAM_INVALID, "添加的年龄超出范围(18-100)");
        }

        //性别校验
        if (!UserGneder.pan(gender)) {
            throw new SandException(AppHttpCodeEnum.PARAM_INVALID, "性别错误");
        }

        //新增时电话号码校验
        if (i == 1){
            if (phone.length() != 11) {
                throw new SandException(AppHttpCodeEnum.PARAM_INVALID, "电话号码长度为11位");
            }

            //电话号码唯一校验
            User one = this.getOne(new LambdaQueryWrapper<User>().eq(User::getPhone, phone));

            if (one != null) {
                throw new SandException(AppHttpCodeEnum.PARAM_INVALID, "该电话号码已经注册");
            }
        }

        //密码校验
        if (password.length() > 10) {
            throw new SandException(AppHttpCodeEnum.PARAM_INVALID, "密码长度格式错误");
        }

        //类型校验(添加用户时校验)
        if (i == 1){
            if (!UserType.pan(type)) {
                throw new SandException(AppHttpCodeEnum.PARAM_INVALID, "用户类型错误");
            }
        }

        //修改时(需要校验地址和描述)
        if (i == 0){

            if (addr.length() > 100){
                throw new SandException(AppHttpCodeEnum.PARAM_INVALID,"添加的地址长度要小于100");
            }

            if (text.length() > 100){
                throw new SandException(AppHttpCodeEnum.PARAM_INVALID,"添加的个人描述长度要小于100");
            }

        }


        //默认添加的用户存在
        user.setStatus(UserStatus.EXIST);

    }


    /**
     * 添加用户的非空字段判断
     */
    private void panNull(User user , Integer i) {

        String name = user.getName();
        Integer age = user.getAge();
        Integer gender = user.getGender();
        Integer type = user.getType();
        String phone = user.getPhone();
        String password = user.getPassword();

        if (name == null || name.isEmpty()) {
            throw new SandException(AppHttpCodeEnum.PARAM_INVALID, "没有传入姓名");
        }

        if (age == null) {
            throw new SandException(AppHttpCodeEnum.PARAM_INVALID, "没有传入年龄");
        }

        if (gender == null) {
            throw new SandException(AppHttpCodeEnum.PARAM_INVALID, "没有传入性别");
        }

        if (i == 1){
            if (type == null) {
                throw new SandException(AppHttpCodeEnum.PARAM_INVALID, "没有传入类型");
            }
        }

        if (i == 1){
            if (phone == null || phone.isEmpty()) {
                throw new SandException(AppHttpCodeEnum.PARAM_INVALID, "没有传入手机");
            }
        }

        if (password == null || password.isEmpty()) {
            throw new SandException(AppHttpCodeEnum.PARAM_INVALID, "没有传入密码");
        }
    }


    /**
     * 添加到对应的人员表
     */
    private void addUser(User user) {

        if (user.getType() == UserType.MERCHANT) {
            //添加到商家表的请求参数
            AddMerchant addMerchant = new AddMerchant(user.getId(), this.permission);

            //发送请求
            merchantFeign.addMerchant(addMerchant);

            return;
        }

        if (user.getType() == UserType.OWNER) {
            //添加到客户表
            AddOwner addOwner = new AddOwner(user.getId(), this.intentionality);

            ownerFeign.addOwner(addOwner);

            return;

        }

        if (user.getType() == UserType.WORKER) {
            //添加到工人表
            AddWorker addOrWorker = new AddWorker(user.getId(), this.workertype);

            workerFeign.add(addOrWorker);


            return;
        }

        if (user.getType() == UserType.SUPPLIER) {
            //添加到供货商表
            AddSupplier addSupplier = new AddSupplier(user.getId());

            supplierFeign.add(addSupplier);


        }

    }


}
